#include <stdio.h>
#include <stdlib.h>
#include "mpx_supt.h"
#include "mrj_supt.h"
#include "r1.h"

void load_cmd(char*);
void kill_cmd(char*);
void pcb_setp(char*);

char Cmd_Prompt[20];
char Cmd_Hist[5][100];
int Hist_Index;


void setCmdPrompt(char* nprompt){
	strcpy(Cmd_Prompt, nprompt);
}


void cmd_handler(){
	char input_buf[80];
	int tbuf_size = 80;
	char** tokens;
	
	printf("%s ", Cmd_Prompt);
	sys_req(READ, TERMINAL, input_buf, &tbuf_size);
	tokens = parse_cmd(input_buf);
		
	strcpy(Cmd_Hist, input_buf);
	Hist_Index = (Hist_Index++)%5;
		
    //printf("cmdline: %s %s\n", tokens[0], tokens[1]);
    if(!strcmp(tokens[0], "date")){
		int arglen = strlen(tokens[1]);
		if( arglen > 0){
			date_cmd(tokens[1]);
		}
		else{
			display_date();
		}
    }
    else if(!strcmp(tokens[0], "cls")){
		clear_screen();
    }
    else if(!strcmp(tokens[0], "ls")){
		list_dir(tokens[1]);
    }
	else if(!strcmp(tokens[0], "hist")){
		show_cmd_history();
	}
    else if(!strcmp(tokens[0], "help")){
		help(tokens[1]);
    }
    else if(!strcmp(tokens[0], "pcb")){
		pcb_function(tokens[1]);
    }
	else if(!strcmp(tokens[0], "prompt")){
		setCmdPrompt(tokens[1]);
	}
    else if(!strcmp(tokens[0], "vrsn")){
		display_version();
    }
    //cmd to load process
    else if(!strcmp(tokens[0], "load")){
		load_cmd(tokens[1]);
    }
    //cmd to kill process
    else if(!strcmp(tokens[0], "kill")){
		kill_cmd(remove_ws(tokens[1]));
    }
	else if(!strcmp(tokens[0], "exit")){
		terminateMPX();
    }
    else{
		printf("\"%s\" unrecognized command.\n", tokens[0]);
    }
    free(tokens[0]);
    free(tokens[1]);
    free(tokens);
}

//parses cmd and arguments from input buffer. returns array of "tokens"
char** parse_cmd(char* input){
        char** token_list = (char**)malloc(2 * sizeof(char*));
        int eos = strlen(input);
        int i=0;
        int j=0;
        token_list[0] = (char*)malloc(50 * sizeof(char));
        token_list[1] = (char*)malloc(80 * sizeof(char));

        while((input[i]==' ')||(input[i]=='\t') && i<eos){
                i++;
        }
        while((input[eos-1]==' ')||(input[eos-1]=='\t')||(input[eos-1]=='\n')){
                eos--;
        }

        while(!((input[i]==' ')||(input[i]=='\n')||(input[i]=='\t'))&& i<eos){
                token_list[0][j] = tolower(input[i]);
                j++;
                i++;
                }
        token_list[0][j]='\0';
        while((input[i]==' ')||(input[i]=='\t') && i<eos){
                i++;
        }
        j=0;
        while(i<eos){
                token_list[1][j] = tolower(input[i]);
                j++;
                i++;
        }
        token_list[1][j]='\0';
        //printf("parse_cmd token_list %s | %s\n", token_list[0], token_list[1]);
        return token_list;
}

//main argument handler for pcb controls
void pcb_function(char* pcbCmd){
        char** tokens = parse_cmd(pcbCmd);
	if(!strcmp(tokens[0], "-suspend")){
                suspend_pcb(remove_ws(tokens[1]));
        }
        else if(!strcmp(tokens[0], "-resume")){
                resume_pcb(remove_ws(tokens[1]));
        }
        else if(!strcmp(tokens[0], "-setp")){
                pcb_setp(tokens[1]);
        }
		else if(!strcmp(tokens[0], "-blok")){
                block_pcb(tokens[1]); //no parameters?
        }
		else if(!strcmp(tokens[0], "-unblok")){
                unblock_pcb(tokens[1]); //no parameters?
        }
        else if(!strcmp(tokens[0], "-info")){
                pcb_info(remove_ws(tokens[1]));
        }
		else if(!strcmp(tokens[0], "-showall")){
                printReady();
				printBlocked();
        }
        else if(!strcmp(tokens[0], "-ready")){
                printReady();
        }
        else if(!strcmp(tokens[0], "-blokked")){
                printBlocked();
        }
        else{
                printf("Error: \"%s\" is not a valid PCB argument. Use \"help pcb\"%s\n", tokens[0], tokens[1]);
        }
        free(tokens[0]);
        free(tokens[1]);
        free(tokens);
}   


void load_cmd(char* arg_line){
	char** args = parse_cmd(arg_line);
	int i;
	printf("load cmd args[1]:%s\n", args[1]);
	printf("%s\n", arg_line);
	if(searchPCBbyName(args[0])==0){
		if(args[1]==NULL){
			load_process(args[0], 0);
		}else{
			printf("parsed priority= %d\n", strint(args[1]));
			load_process(args[0], strint(args[1]));
		}
	}
	else{
		printf("Load fail. Process already exists.\n");
	}
}


//assuming pcb->Pclass 0 is system process
void kill_cmd(char* pName){
	pcb* pbj = searchPCBbyName(pName);
	if(pbj!=0){
		if(pbj->Pclass == 1){
			free_pcb(pbj);
		}else{
			printf("Could not terminate process %s. It is a system process.\n", pName);
		}
	}else{
		printf("Could not terminate process %s. Does Not Exist.\n", pName);
	}
}

void show_cmd_history(){
	int i;
	printf("Last 5 commands entered:\n");
	for(i=0; i<Hist_Index; i++){
		printf("\t%s", Cmd_Hist[i]);
	}
	printf("\0");
}

void pcb_setp(char* argStr){
	char** argS = parse_cmd(argStr);
	char* pName = remove_ws(argS[0]);
	int new_priority = strint(remove_ws(argS[1]));
	printf("%s pcb_setp: pri: %d\n", pName, new_priority);
	//Check to see if priority is valid; between -128 and 127
	if((new_priority < -128) || (new_priority > 127)){
		printf("ERROR: Process priority is invalid, please enter a value\nbetween -128 and 127\n");
	}
	else{
		pcb* pcbid = searchPCBbyName(pName);
		if(pcbid){
			pcbid->priority = new_priority;
			printf("%s priority has been changed to %d.\n", pcbid->name, pcbid->priority);
		}
		else{
			printf("Failed to set priority. Process DNE\n");
		}
	}
}